home *** CD-ROM | disk | FTP | other *** search
/ 9-Digit Zip Code Directory / 9-Digit Zip Code Directory (American Business Information) (ABIZIP-12).ISO / z4src.zip / CPSTRING.C < prev    next >
C/C++ Source or Header  |  1993-06-08  |  8KB  |  277 lines

  1. //----------------------------------------------------------------------------
  2. //                            MODULE DESCRIPTION
  3. //
  4. //  Module:    cpstring.c
  5. //   Title:    Data Compression Library
  6. //  Notice:    John M. Weeder
  7. //                 Copyright (c) 1993. All rights reserved.
  8. //             This module contains proprietary information and should be 
  9. //                treated as confidential.
  10. //
  11. //----------------------------------------------------------------------------
  12. //                           MAINTENANCE HISTORY
  13. //
  14. // $Workfile$
  15. // $Revision$
  16. //   $Author$
  17. //     $Date$
  18. //      $Log$    
  19. //
  20. //----------------------------------------------------------------------------
  21. //                             MODULE NARRATIVE
  22. //
  23. //
  24. //    This module contains a string encoding function. It uses a combination of
  25. //    nybble encoding and word caching to compress a string.
  26. //
  27. //    The code in this module should be written entirely in C. 
  28. //    Do not use any C++ constructs.
  29. //
  30. //    This module is portable to:
  31. //        DOS 3.X+
  32. //        MS Windows 3.X+
  33. //        OS/2 2.X+
  34. //        OS/2 2.0 PM
  35. //        SCO UNIX.
  36. //
  37. //    The following compilers are supported:
  38. //        MSC 6.0A
  39. //        MSC/C++ 7.0
  40. //        Borland C++ 3.1 for DOS
  41. //        Borland C++ 1.0 for OS/2 2.X
  42. //        SCO UNIX cc
  43. //
  44. //----------------------------------------------------------------------------
  45. #include <cp.h>
  46.  
  47.  
  48. //----------------------------------------------------------------------------
  49. //   Description:    Decode a string buffer
  50. //    Parameters:    pv                    Pointer to word cache.
  51. //                        pbDecode            Pointer to buffer to decode.
  52. //                        pcDecode            Pointer to receive number of bytes decoded.
  53. //                        pch                Buffer to place decoded text into.
  54. //                                            Null terminator is added to buffer.
  55. //                                            Buffer is assumed to be of sufficient size.
  56. //       Returns:    TRUE if successful.
  57. //----------------------------------------------------------------------------
  58. BOOL FN_E StringDecode(PVOID pv, PBYTE pbDecode, PSIZET pcDecode, PCHAR pch)
  59. {
  60.     SIZET cNybble;
  61.     SIZET cDecode = 0;
  62.     BOOL fFirst = TRUE;
  63.     PCHAR pchSave = pch;
  64.  
  65.     Assert(pv && pbDecode && pcDecode && pch);
  66.     *pch = '\0';                                // Start with an empty string
  67.  
  68.     while (*pbDecode)
  69.         {
  70.         if (!fFirst)                            // Insert spaces between words
  71.             {
  72.             *pch++ = ' ';
  73.             *pch = '\0';
  74.             }
  75.         if ((*pbDecode) & 0x80)                // A cached word
  76.             {
  77.             strcpy(pch, WordDecode(pv, *pbDecode));
  78.             cDecode++;
  79.             pbDecode++;
  80.             }                             // Final word
  81.         else if (((*pbDecode) & 0x40)
  82.         && *pbDecode != 0x7F)
  83.             {
  84.             pbDecode[0] &= ~0x40;
  85.             NybbleDecode(pbDecode, &cNybble, pch);
  86.             pbDecode[0] |= 0x40;
  87.             WordEncode(pv, pch, TRUE);        // Update cache
  88.             cDecode += cNybble;
  89.             *pcDecode = cDecode;
  90.             if (pchSave[0] && pchSave[1])    // Update cache w/ whole string
  91.                 WordEncode(pv, pchSave, TRUE);
  92.             return TRUE;
  93.             }
  94.         else                                        // A nybble encoded sequence
  95.             {
  96.             NybbleDecode(pbDecode, &cNybble, pch);
  97.             WordEncode(pv, pch, TRUE);        // Update cache
  98.             cDecode += cNybble;
  99.             pbDecode += cNybble;
  100.             }
  101.         pch = strchr( pch, '\0');
  102.         fFirst = FALSE;
  103.         }
  104.     *pcDecode = cDecode + 1;                // + 1 for final 0 byte
  105.     if (pchSave[0] && pchSave[1])            // Update cache w/ whole string
  106.         WordEncode(pv, pchSave, TRUE);
  107.     return TRUE;
  108. }
  109.  
  110.  
  111. //----------------------------------------------------------------------------
  112. //   Description:    Encode a string
  113. //    Parameters:    pbEncode            Pointer to buffer to encode into.
  114. //                        pcEncode            Pointer to variable to recieve size of
  115. //                                            encoded text.
  116. //                                            Buffer must be of sufficient size.
  117. //                                            Maximum size is strlen(pcsz)+2.
  118. //                        pcsz                Buffer to read text from.
  119. //       Returns:    TRUE if successful.
  120. //----------------------------------------------------------------------------
  121. BOOL FN_E StringEncode(PVOID pv, PBYTE pbEncode, PSIZET pcEncode, PCSZ pcsz)
  122. {
  123.     SIZET cEncode = 0;
  124.     PSZ psz = (PSZ)pcsz;
  125.     PSZ pszSpace;
  126.     CHAR ch;
  127.     BYTE bVal;
  128.  
  129.     if (!psz[0])                                // Special case of zero length
  130.         {                                            // string!
  131.         *pbEncode = 0;
  132.         *pcEncode = 1;
  133.         return TRUE;
  134.         }
  135.     bVal = WordEncode(pv, psz, FALSE);    // Encode entire string
  136.     if (bVal)                                    // Entire string already cached!
  137.         {
  138.         *pbEncode++ = bVal;
  139.         cEncode++;
  140.         *pbEncode = 0;                            // Final word is cached, add
  141.         cEncode++;                                //  trailing null
  142.         psz = strchr(psz, '\0');            // Move to end of string
  143.         }
  144.     while (psz[0])
  145.         {
  146.         pszSpace = psz;                        // Skip leading spaces
  147.         while (pszSpace[0] && pszSpace[0] == ' ')
  148.             pszSpace++;
  149.                                                     // Skip to end of word
  150.         while (pszSpace[0] && pszSpace[0] != ' ')
  151.             pszSpace++;
  152.                                                     // Include multiple spaces
  153.         while (pszSpace[0] && (pszSpace[1] == ' ' || pszSpace[1] == '\0'))
  154.             pszSpace++;
  155.  
  156.         ch = *pszSpace;                        // Terminate word
  157.         *pszSpace = '\0';
  158.  
  159.         Assert(strlen(psz) < 63);            // Word limited to 62 characters!
  160.  
  161.         bVal = WordEncode(pv, psz, TRUE);// Encode word
  162.         if (bVal)                                // Word already cached!
  163.             {
  164.             *pbEncode++ = bVal;
  165.             cEncode++;
  166.             if (!ch)                                // Final word is cached, add
  167.                 {                                    //  trailing null
  168.                 *pbEncode = 0;
  169.                 cEncode++;
  170.                 }
  171.             }
  172.         else                                        // Encode as nybble stream
  173.             {
  174.             SIZET cNybble;
  175.             NybbleEncode(pbEncode, &cNybble, psz);
  176.             cEncode += cNybble;
  177.             if (!ch)
  178.                 {
  179.                 if (*pbEncode == 0x7F)        // Final word is uncompressed
  180.                     {                                //  ascii.
  181.                     pbEncode += cNybble;
  182.                     *pbEncode = 0;
  183.                     cEncode++;
  184.                     }
  185.                 else
  186.                     pbEncode[0] |= 0x40;
  187.                 }
  188.             else
  189.                 pbEncode += cNybble;
  190.             }
  191.         *pszSpace = ch;                        // Replace space character
  192.         psz = *pszSpace ? pszSpace + 1: pszSpace;
  193.         }
  194.     *pcEncode = cEncode;                        // Return length of encoded string
  195.     if (pcsz[0] && pcsz[1])                    // Don't encode trivial strings
  196.         WordEncode(pv, pcsz, TRUE);        // Update cache w/ whole string
  197.     return TRUE;
  198. }
  199.  
  200.  
  201. //----------------------------------------------------------------------------
  202. //   Description:    Run standard test suite
  203. //    Parameters:    sTest        Test to run.
  204. //                                        0        Run all default tests (except).
  205. //       Returns:    TRUE if successful.
  206. //----------------------------------------------------------------------------
  207. #if COMPILE_TEST
  208. BOOL FN StringTest(SHORT sTest)
  209. {
  210. static CHAR szBuf[80];
  211. static BYTE bBuf[1024];
  212.  
  213. static PSZ apsz[] =
  214.     {
  215.     "5TH & L ST",                                // Ampersand
  216.     "",                                            // Empty
  217.     " ",                                            // Single space
  218.     "  ",                                  // Only spaces
  219.     "   ",
  220.     "          ",
  221.     "EEEE EEEE EEEE EEEE",                    // Single spaces
  222.     "SEE THE BROWN FOX JUMP",                // Two identical string
  223.     "SEE THE BROWN FOX JUMP",
  224.     "SEE THE BROWN FOX ",                    // A partial match
  225.     "THIS IS A TEST OF THE TEST OF A THIS AND A WORD ",
  226.     " WORD   WORD   WORD WORD WORD ",    // Multiple spaces
  227.     "E",                                            // Should take only 2 bytes
  228.     "E",                                            // Single char
  229.     "EAOIUSTRLNDMCPH",                        // All nybble
  230.     "FBWYKGVJXQZ-/#&",                        // All byte
  231.     "1234567890",                                // 2 Byte
  232.     "EF1B2AB2OWW3IIY4UK5SG6TV7",            // A mix
  233.     NULL
  234.     };
  235.     PVOID pv;
  236.     SIZET i;
  237.     SIZET cEncode = 0, cDecode = 0;
  238.  
  239.     NOTUSED(sTest);
  240.     pv = StringCreate(512, CP_WORD_VERIFY);
  241.     if (pv == FALSE)
  242.         return FALSE;
  243.  
  244.     for (i = 0; apsz[i]; ++i)                // Encode the strings
  245.         {
  246.         SIZET cString;
  247.         StringEncode(pv, bBuf + cEncode, &cString, apsz[i]);
  248.         cEncode += cString;
  249.         }
  250.     StringReset(pv);
  251.     for (i = 0; apsz[i]; ++i)                // Encode the strings
  252.         {
  253.         SIZET cString;
  254.         StringDecode(pv, bBuf + cDecode, &cString, szBuf);
  255.         cDecode += cString;
  256.         Output(" Input: (%3d) %s\n", strlen(apsz[i])+1, apsz[i]);
  257.         Output("Output: (%3d) %s\n", strlen(szBuf)+1,   szBuf);
  258.         Output(" Bytes:  %3d\n", cString);
  259.         if (strcmp(apsz[i], szBuf) != 0)
  260.             {
  261.             StringDestroy(pv);
  262.             return FALSE;
  263.             }
  264.         }
  265.     if (cEncode != cDecode)
  266.         {
  267.         StringDestroy(pv);
  268.         return FALSE;
  269.         }
  270.     StringDestroy(pv);
  271.     return TRUE;
  272. }
  273. #endif
  274. //----------------------------------------------------------------------------
  275. //------------------------------- End of File --------------------------------
  276. //----------------------------------------------------------------------------
  277.